import SparkMD5 from 'spark-md5'
import axios from 'axios'
axios.defaults.baseURL = "http://123.249.0.201"
// axios.defaults.baseURL = "http://localhost:8080"

// 文件传输逻辑
const cfile = {};


// 返回文件目录
const token = localStorage.getItem("TOKEN")
// const File_Pathss = []
// cfile.File_Pathss = File_Pathss


// cfile.test = () => {
    //     return new Promise((resolve, reject) => {
        //         setTimeout(() => {
            //             File_Pathss.push(10)
            //             console.log("test out");
            //             resolve()
            //         }, 1000)
            //     })
            // }

// 导出文件返回目录
cfile.File_Path = []


// 获取文件 直接获取
cfile.user_files = []
cfile.selectFilesDirect = (f) => {
    cfile.user_files.push(f);
}


// 获取文件 通过表单事件
cfile.selectFilesForm = (e) => {

    let files = e.target.files
    for (let i = 0; i < files.length; i++) {
        cfile.user_files.push(files[i]);
    }
}


// 文件上传
cfile.uploadFile = (callback) => {
    let chunk_size = 1024 * 1024 * 5;  // 5Mb分块
    let max_chunk = 5242880;  // 最大不分块大小 5242880字节 5Mb
    let url = "/upload";
    let headers = {
        'Content-Type': 'multipart/form-data',
        'authorization': token
    }

    for (let i = cfile.user_files.length - 1; i >= 0; i--) {
        let f = cfile.user_files.pop(i)
        // console.log(i);
        // console.log("cfile.user_files", cfile.user_files);
        let file_self = f;
        let file_name = f.name
        let file_size = f.size
        let file_hash = null;
        let file_arr = [];
        let chunk_msg = []

        if (file_size < max_chunk) {
            // 直接发送
            createFileHash(file_self, file_name).then(hash => {
                // 获取文件hash
                let form_data = new FormData();
                // form_data.append("user_id", user_id)
                form_data.append("file_name", file_name)
                form_data.append("file_hash", hash);
                form_data.append("file_index", "0")
                form_data.append("file", file_self)  // file 要放在最后 multer的文件捕获会截取file之前的form

                chunk_msg.push(url, form_data, { headers: headers })
                // 文件信息表
                file_arr.push(chunk_msg)
                chunk_msg = [];
                // 异步并发 结束执行回调 单文件不进行合并请求
                sendRequest(file_arr, () => {
                    callback()
                })  // 回调函数内不能传参数
            })

        } else {
            // 切片发送
            let file_index = 0;

            createFileHash(file_self, file_name).then(hash => {
                // 获取文件hash
                for (let start_size = 0; start_size < file_size; start_size += chunk_size) {
                    let blob = null;

                    // 文件切片
                    if (start_size + chunk_size > file_size) {
                        // 末切片
                        blob = file_self.slice(start_size, file_size);
                    } else {
                        blob = file_self.slice(start_size, chunk_size * (file_index + 1));
                    }

                    let file_ext = file_name.substring(file_name.lastIndexOf(".") + 1)
                    let blob_name = file_index + "-" + file_hash + "." + file_ext

                    // 新建文件？
                    let blob_file = new File([blob], blob_name);
                    let form_data = new FormData();

                    // form_data.append("user_id", user_id)
                    form_data.append("file_name", file_name)
                    form_data.append("file_hash", hash)
                    form_data.append("file_index", file_index + "")
                    form_data.append("file", blob_file)

                    chunk_msg.push(url, form_data, { headers: headers })
                    // 文件信息表
                    file_arr.push(chunk_msg)
                    chunk_msg = [];

                    file_index += 1;
                }
                // 获取文件切片数
                let chunk_num = file_index;

                // 异步并发 结束执行回调
                sendRequest(file_arr, () => after_uploadFile(hash, chunk_num, callback))
            })
        }
    }
}


// 创建文件hash
function createFileHash(file, file_name) {

    // 处理抽样hash切片大小!!!!!!!!!!!!!!
    const hash_chunk = 512;

    return new Promise((resolve, reject) => {
        const spark = new SparkMD5.ArrayBuffer()
        const reader = new FileReader()
        reader.readAsArrayBuffer(file)

        reader.addEventListener("loadend", () => {
            const content = reader.result  // 读取结果

            // 切片hash 取前十个字符
            for (let i = 0; hash_chunk * i < file.size; i++) {
                spark.append(content.slice(hash_chunk / 2 * i, hash_chunk / 2 * i + 10))  // 向md5添加读取结果
            }
            const hash = spark.end()  // 获取hash
            resolve(hash, content)
        })

        reader.addEventListener('error', function _error(err) {
        reject(err)
        })
    })
}


// 异步并发
function sendRequest(arr, callback) {

    let max_index = 5  // 设置最大执行数量
    let arr_index = 0
    let req_arr = []

    let endReq = () => {

        // 异步任务执行至最后 结束并发
        if (arr_index === arr.length) {
            return Promise.resolve()
        }

        let req_msg = arr[arr_index++]

        // 发送事件
        let res_msg = axios.post(req_msg[0], req_msg[1], req_msg[2]);
        req_arr.push(res_msg)
        res_msg.then((res) => {  // 在此处获得res

            // 单文件的料理方式
            if (res.data.file_path) {
                // console.log(res.data.file_path);
                // console.log(res.data.msg);
                cfile.File_Path.push(res.data.file_path);
                // callback()
                // cfile.File_Path.push(res.data.file_path)
                // console.log(" File_Path[0]",  File_Path[0]);
            } else if (res.data.msg !== "Cool" && arr_index === 1) {
                console.log(res.data.msg);
            };
            // 在此处可以协调进行断点重发？

            req_arr.splice(req_arr.indexOf(res_msg), 1)  // 移除发送完毕的请求
        }).catch((error) => {
            console.log("发送失败", error);
        });
        // req_arr.push(res_msg)

        // 如果并发数量达到上限则等待其中一个完成再添加
        let promise = Promise.resolve()
        if (req_arr.length >= max_index) {
            promise = Promise.race(req_arr)
        };

        // 递归执行endReq()
        return promise.then(() => endReq())
    }

    endReq().then(() => {
        // 全部执行完成执行回调函数
        Promise.all(req_arr).then(() => {
            callback()
        }).catch((error) => {
            console.log("请求错误 请重新登录", error);
        })
    })
}


// 文件上传回调
function after_uploadFile(file_hash, chunk_num, callback) {
    let url = "/upload/merge";
    let req_msg = {
        "file_hash": file_hash,
        "chunk_num": chunk_num,
    }
    let headers = {
        'authorization': token
    }

    // 大文件切片的料理方式
    axios.post(url, req_msg, {headers: headers}).then((res) => {
        if (res.data.file_path) {
            // console.log(res.data.file_path);
            cfile.File_Path.push(res.data.file_path);
        }
        callback()
        // console.log(res.data.msg);
        return ;
    }).catch((error) => {
        console.log(error);
        return ;
    });
}


export default cfile;